<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    .cvs{
      border: solid 1px black;
    }
  </style>
</head>
<body>
  <canvas class="cvs"></canvas>
  <input type="button" value="生成图片" class="btn1">
  <input type="button" value="下载" class="btn2">
  <img src="" alt="" class="img">
</body>
<script>

  const cvs = document.querySelector(".cvs")

  cvs.width = 400;
  cvs.height = 400;

  const ctx = cvs.getContext("2d")

  // 绘制初始表盘信息
  clock();

  // 获取实时事件，重新绘制表盘
  setInterval(clock, 1000);

  function clock(){
    // 擦除之前
    ctx.clearRect(0, 0, cvs.width, cvs.height);
    // 重新开始路径
    ctx.beginPath();
    // 获取日期
    const d = new Date();
    // 获取时分秒
    const s = d.getSeconds();
    const m = d.getMinutes();
    const h = d.getHours();

    // 绘制秒针
    drawLine(ctx, {
      deg: 360 / 60 * s, 
      start:20, 
      length:-120
    })

    // 绘制分针
    drawLine(ctx, {
      deg: 360 / 60 * m,
      start:14, 
      length:-90
    })

    // 绘制时针
    drawLine(ctx, {
      deg: 360 / 12 * h + (360/12/60 * m), 
      start:10, 
      length:-60
    })

    // 绘制中心点
    ctx.beginPath();
    ctx.arc(200, 200, 5, 0, 2 * Math.PI);
    ctx.fill();
    
    // 绘制表圈
    ctx.beginPath();
    ctx.arc(200, 200, 100, 0, 2 * Math.PI);
    ctx.stroke();

    // 绘制刻度
    const r = 80;
    for(let i=0;i<60;i++){
      let l = i%5 === 0 ? 12 : 6;
      drawLine(ctx, {
        deg: 360 / 60 * i, 
        start: -100, 
        length: l
      })
    }
    // 绘制数字
    for(let i=0;i<12;i++){
      const x = Math.cos( dtr(360/12*i - 60) ) * r + 200;
      const y = Math.sin( dtr(360/12*i - 60) ) * r + 200;
      ctx.textAlign = "center";
      ctx.textBaseline = "middle";
      ctx.font = "16px 黑体";
      ctx.fillText( i+1, x, y );
    }
    // 绘制品牌
    ctx.fillText( "劳力士", 200, 220 );
  }


  // 划线功能：画笔对象，配置对象
    // 配置对象：角度，起始位置，长度
  function drawLine(ctx, {deg, start, length}){
    ctx.beginPath();
    ctx.save();
    ctx.translate(200, 200);
    ctx.rotate( dtr(deg) );
    ctx.lineWidth = 2;
    ctx.moveTo(0, start);
    ctx.lineTo(0, start + length);
    ctx.stroke();
    ctx.restore();
  }

  // 角度转弧度
  function dtr(deg){
    return Math.PI/180*deg;
  }

  // =======

  const btn1 = document.querySelector(".btn1");
  const btn2 = document.querySelector(".btn2");
  const img = document.querySelector(".img");
  btn1.onclick = function(){
    const base64 = cvs.toDataURL("image/png");
    img.src = base64;
  }

  btn2.onclick = function(){
    // 将canvas数据转成base64数据
    const base64 = cvs.toDataURL("image/png");
    // 将base64数据解码
    const strBase64 = atob( base64.split(",")[1] );
    // 创建utf-8原始数据（长度为base64解码后的字符长度）
    const utf_8 = new Uint8Array(strBase64.length);
    // 将base64解码后的数据转成Unicode编码后，存入utf-8数组
    for(let n=0;n<strBase64.length;n++){
      utf_8[n] = strBase64.charCodeAt(n)
    }
    // 根据utf-8数据，创建文件对象
    const file = new File([utf_8], "测试图片", {type:"image/png"});
    // 根据文件对象创建url字符
    const href = URL.createObjectURL(file);
    // 准备a标签，用于下载文件
    const a = document.createElement("a");
    a.href = href;
    a.download = "测试图片123";
    document.body.appendChild(a);
    a.click();
    // 删除a标签
    a.remove();
    // 释放指向文件资源的url字符
    URL.revokeObjectURL(href);
  }
  
</script>
</html>